import base64
import quopri
import re
# import module.UpExcel as moduleExcel
import os
from email.utils import parseaddr, parsedate, getaddresses
from email.header import decode_header, Header
from email.parser import Parser
# import xlwings as xw
import time
import email
import datetime
import poplib
# import pandas as pd


# poplib._MAXLINE = 20480

# # 此函数通过使用poplib实现接收邮件
# email_address =
# email_password =


def recv_email_by_pop3():
    # 要进行邮件接收的邮箱。改成自己的邮箱
    # email_address = ""
    # 要进行邮件接收的邮箱的密码。改成自己的邮箱的密码
    # 设置 -> 账户 -> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 -> 开启服务：POP3/SMTP服务
    # 设置 -> 账户 -> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 -> 生成授权码
    # email_password = ""
    # 邮箱对应的pop服务器，也可以直接是IP地址
    # 改成自己邮箱的pop服务器；
    pop_server_host = "mail.nsfocus.com"
    # 邮箱对应的pop服务器的监听端口。改成自己邮箱的pop服务器的端口；qq邮箱不需要修改此值
    pop_server_port = 996
    # 连接pop服务器。如果没有使用SSL，将POP3_SSL()改成POP3()即可其他都不需要做改动
    email_server = poplib.POP3_SSL(host=pop_server_host, timeout=30, port=pop_server_port)
    email_server.user('ar')
    email_server.pass_('u32Te7sAM')
    # 邮箱中其收到的邮件的数量
    email_count = len(email_server.list()[1])
    # print(email_count, '-----------------count')
    # list()返回所有邮件的编号:
    resp, mails, octets = email_server.list()
    # print(mails)
    # 遍历所有的邮件
    print(len(mails), '------------3')
    for i in range(len(mails)-1, 2, -1):
        # 通过retr(index)读取第index封邮件的内容；这里读取最后一封，也即最新收到的那一封邮件
        resp, lines, octets = email_server.retr(i)
        # lines是邮件内容，列表形式使用join拼成一个byte变量
        # print(lines)
        email_content = b'\r\n'.join(lines)
        # print(email_content)
        try:
            # 再将邮件内容由byte转成str类型
            # print(email_content)
            email_content = email_content.decode('utf-8')
            # print(email_content)
            # print(email_content)
            # ea = re.match(r"PGh.*==", email_content)
            # print(ea, '-----------------ea')
        except Exception as e:
            print(str(e))
            continue
        # # 将str类型转换成<class 'email.message.Message'>
        # msg = email.message_from_string(email_content)
        msg = Parser().parsestr(email_content)
        # print(msg)
        header = msg.get('Subject', '')
        sub = header.split(':')
        print(sub[1])
        # # print(msg, '------------------1')
        b_msg = msg.get_payload()
        # print(b_msg[1])
        html_msg = quopri.decodestring(str(b_msg[1])).decode('utf-8')
        # print(html_msg)


        # # print(b_msg, '------------------2')
        # # html_msg = base64.b64decode(b_msg)
        # html_msg = quopri.decodestring(email_content)
        # print(html_msg)
        # html_msg = html_msg.decode('utf-8')
        # header = msg.get('Subject', '')
        # header2 = re.findall(r"\?.*?\?", header)
        # char_type = header2[0].replace('?', '')
        # i = header2[1].replace('?', '')
        # i = base64.b64decode(i).decode(char_type)
        # print(i)
        # sub = i + header2[3].replace('?', '')
        # sub = sub.split(':')
        # time_str = time.strftime("%Y%m%d-%H%M")
        # now_sub = time_str + '-' + sub[1]
        # print(now_sub)

        # print(header)
        # print(b_msg)
        # html_msg = base64.b64decode(b_msg)
        # print(html_msg)
        # print('-----------------')
        # html_msg = html_msg.decode('utf-8')
        # print(html_msg)
        with open('res_html.html', 'w', encoding='utf-8') as f:
            f.write(html_msg)
        print('-------------  分隔符  ---------------')
        # print(msg)
        # # 写入邮件内容到文件
        # list = []
        # list = parse_email(list, msg, 0, interval_day)
        # # 时间判断
        # nowTime = (datetime.datetime.now() + datetime.timedelta(days=interval_day)
        #            ).strftime("%Y-%m-%d") + ' 00:00:00'
        # if list[0] < nowTime:
        #     email_server.close()
        #     return/
        # if len(list) > 2:
        #     riqi = str(time.strftime("%Y-%m-%d", time.localtime()))
        #     filename = r'D:\AutoEmail\Get\Get' + riqi + '.xlsx'
        #     app = xw.App(visible=False, add_book=False)
        #     wb = app.books.open(filename)  # 读入已有工作簿
        #     sht = wb.sheets[0]  # 引用活动sheet
        #     info = sht.used_range
        #     nrows = info.last_cell.row
        #     sht.range('A' + str(nrows + 1)).value = [list]
        #     # 自动调整表格
        #     # sht.autofit()
        #     info.column_width = 40
        #     sht.range('A1:A' + str(nrows + 1)).column_width = 16
        #     # 保存工作簿
        #     wb.save(filename)
        #     wb.close()  # 关闭工作簿(程序不能编辑了)----显示的文件不关闭
        #     # app.quit()  # 退出
        #     app.kill()

    # 关闭连接
    email_server.close()


# 下载附件


# def get_att(msg):
#     attachment_files = []
#     for part in msg.walk():
#         file_name = part.get_filename()  # 获取附件名称类型
#         contentType = part.get_content_type()  # 获取数据类型
#         mycode = part.get_content_charset()  # 获取编码格式
#         if file_name:
#             h = Header(file_name)
#             dh = decode_header(h)  # 对附件名称进行解码
#             filename = dh[0][0]
#             if dh[0][1]:
#                 filename = decode_str(str(filename, dh[0][1]))  # 将附件名称可读化
#             attachment_files.append(filename)
#             data = part.get_payload(decode=True)  # 下载附件
#             with open(filename, 'wb') as f:  # 在当前目录下创建文件，注意二进制文件需要用wb模式打开
#                 #with open('指定目录路径'+filename, 'wb') as f: 也可以指定下载目录
#                 f.write(data)  # 保存附件
#             print(f'附件 {filename} 已下载完成')
#         elif contentType == 'text/plain':  # or contentType == 'text/html':
#             # 输出正文 也可以写入文件
#             data = part.get_payload(decode=True)
#             content = data.decode(mycode)
#             print('正文：', content)
#     print('附件文件名列表', attachment_files)

# 读取信息（ indent用于缩进显示:）


def parse_email(list, msg, indent, interval_day):
    if indent == 0:
        # print('msg:',msg)
        # 邮件的From, To, Subject存在于根对象上:
        for header in ['Date', 'From', 'To', 'CC', 'Subject']:
            value = msg.get(header, '')
            # if value:
            # 时间
            if header == 'Date':
                strDate = time.strftime("%Y-%m-%d %H:%M:%S", parsedate(value))
                # 获取当日发件
                nowTime = (datetime.datetime.now(
                ) + datetime.timedelta(days=interval_day)).strftime("%Y-%m-%d") + ' 00:00:00'
                list.append(strDate)
                if strDate[:10] < nowTime:
                    print('%s%s: %s' % ('  ' * indent, header, strDate))
                    return list
                print('%s%s: %s' % ('  ' * indent, header, strDate))
            # 发件人
            elif header == 'From':
                # 需要解码Email地址:
                hdr, addr = parseaddr(value)
                # name = decode_str(hdr)
                # strFrom = u'%s <%s>' % (name, addr)
                strFrom = u'<%s>' % (addr)
                list.append(strFrom)
                print('%s%s: %s' % ('  ' * indent, header, strFrom))
            # 收件人
            elif header == 'To':
                listTo = []
                tos = msg.get_all('to', [])
                for to in getaddresses(tos):
                    to = to[0] + ' <' + to[1] + '>'
                    hdr, addr = parseaddr(to)
                    name = decode_str(hdr)
                    # strTo = u'%s <%s>' % (name, addr)
                    strTo = u'<%s>' % (addr)
                    listTo.append(strTo)
                strlistto = ''.join(listTo)
                # # 需要解码Email地址:
                # hdr, addr = parseaddr(value)
                # name = decode_str(hdr)
                # strTo = u'%s <%s>' % (name, addr)
                list.append(strlistto)
                print('%s%s: %s' % ('  ' * indent, header, strlistto))
            # 抄送
            elif header == 'CC':
                listCc = []
                ccs = msg.get_all('cc', [])
                for cc in getaddresses(ccs):
                    cc = cc[0] + ' <' + cc[1] + '>'
                    hdr, addr = parseaddr(cc)
                    name = decode_str(hdr)
                    # strCc = u'%s <%s>' % (name, addr)
                    strCc = u'<%s>' % (addr)

                    listCc.append(strCc)
                strlistCc = ''.join(listCc)
                if strlistCc == '':
                    strlistCc = '空'
                # # 需要解码Email地址:
                # hdr, addr = parseaddr(value)
                # name = decode_str(hdr)
                # strCc = u'%s <%s>' % (name, addr)
                list.append(strlistCc)
                print('%s%s: %s' % ('  ' * indent, header, strlistCc))
            # 主题
            elif header == 'Subject':
                # 需要解码Subject字符串:
                strSubject = decode_str(value)
                list.append(strSubject)
                print('%s%s: %s' % ('  ' * indent, header, strSubject))
    if (msg.is_multipart()):
        # 如果邮件对象是一个MIMEMultipart,
        # get_payload()返回list，包含所有的子对象:
        parts = msg.get_payload()
        for n, part in enumerate(parts):
            # 递归打印每一个子对象:
            parse_email(list, part, indent + 1, interval_day)
        return list
    else:
        for part in msg.walk():  # 遍历所有payload
            # 邮件对象不是一个MIMEMultipart,
            # 就根据content_type判断:
            content_type = msg.get_content_type()
            file_name = part.get_filename()
            if content_type == 'text/plain' or content_type == 'text/html':
                if len(list) < 6:
                    # 纯文本或HTML内容:
                    content = msg.get_payload(decode=True)
                    # 要检测文本编码:
                    charset = guess_charset(msg)
                    if charset:
                        try:
                            content = content.decode(charset)
                        except:
                            content = content.decode("gb2312", errors='ignore')
                    print('%sText: %s' % ('  ' * indent, content))
                    list.append('text:' + content.replace(' ',
                                                          '').replace('\n', '').replace('\r', '')[:300])

            if file_name:
                h = email.header.Header(file_name)
                dh = email.header.decode_header(h)  # 对附件名称进行解码
                filename = dh[0][0]
                if dh[0][1]:
                    filename = decode_str(str(filename, dh[0][1]))  # 将附件名称可读化
                    # filename = filename.encode("utf-8")
                data = part.get_payload(decode=True)  # 下载附件

                riqi = str(time.strftime("%Y-%m-%d", time.localtime()))
                attfileadd = 'D:\\AutoEmail\\Att\\Get\\' + riqi
                if not os.access(attfileadd, os.X_OK):
                    os.mkdir('D:\\AutoEmail\\Att\\Get\\' + './' + riqi + '')

                with open(attfileadd + '\\' + filename, 'wb') as f:  # 在当前目录下创建文件，注意二进制文件需要用wb模式打开
                    f.write(data)  # 保存附件
                print('%sAtt: %s' % ('  ' * indent, filename))
                list.append(filename)
            # else:
            #     # 不是文本，作为附件处理:
            #     print('%sAttachment: %s' % ('  ' * indent, content_type))
            #     list.append('Attachment:' + content_type)
    return list


# 解码


def decode_str(s):
    value, charset = decode_header(s)[0]
    # if charset or value[:2]=='Re':
    try:
        value = value.decode(charset)
    except:
        try:
            value = value.decode("gb2312", errors='ignore')
        except:
            pass
    return value


# 猜测字符编码


def guess_charset(msg):
    try:
        # 先从msg对象获取编码:
        charset = msg.get_charset()
        if charset is None:
            # 如果获取不到，再从Content-Type字段获取:
            content_type = msg.get('Content-Type', '').lower()
            for item in content_type.split(';'):
                item = item.strip()
                if item.startswith('charset'):
                    charset = item.split('=')[1]
                    break
        return charset
    except:
        pass


recv_email_by_pop3()
